package com.company;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;

public class ABADemo {
    // 表示内存里初始值是100,版本好号为1
    private static AtomicStampedReference atomicStampedReference=new AtomicStampedReference(100,1);
    public static void main(String[] args) {
        new Thread(()->{
            // 获得版本号
            int stamp = atomicStampedReference.getStamp();
            // 这里延迟一秒不是为了说为了线程阻塞，而是为了让线程B得到版本号
            System.out.println(Thread.currentThread().getName()+"\t第一次版本号："+stamp);
            try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); }
            // 期望值为100 和内存中的值进行比较，如果一样，且版本号stamp也和内存中一样，则改为50
            atomicStampedReference.compareAndSet(100,50,stamp,stamp+1);
            System.out.println(Thread.currentThread().getName()+"\t第二次版本号："+atomicStampedReference.getStamp());
//            atomicStampedReference.compareAndSet(100,50,stamp,stamp+1);
        },"A").start();

        new Thread(()->{
            // 获得版本号
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName()+"\t第一次版本号："+stamp);
            // 线程阻塞
            try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
            // 期望值为100 和内存中的值进行比较，如果一样，且版本号stamp也和内存中一样，则改为50
            boolean result = atomicStampedReference.compareAndSet(100, 50, stamp, stamp + 1);
            System.out.println(Thread.currentThread().getName()+"\t修改是否成功"+result+"\t当前实际版本号："+atomicStampedReference.getStamp());
            System.out.println("当前实际最新值："+atomicStampedReference.getReference());
        },"B").start();

        new Thread(()->{
            // 这里延迟两秒不是为了说为了线程阻塞，而是为了让线程A 执行完毕
            try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); }
            // 获得版本号
            int stamp = atomicStampedReference.getStamp();
            System.out.println(Thread.currentThread().getName()+"\t第一次版本号："+stamp);
            // 期望值为100 和内存中的值进行比较，如果一样，且版本号stamp也和内存中一样，则改为50
            atomicStampedReference.compareAndSet(50,100,stamp,stamp+1);
            System.out.println(Thread.currentThread().getName()+"\t第二次版本号："+atomicStampedReference.getStamp());
        },"C").start();
    }
}
